package com.pointcircle.estate.server.framework.web.api;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.stream.Collectors;

import javax.validation.Valid;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.Size;

import org.apache.commons.lang3.StringUtils;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.pointcircle.core.IRepository;
import com.pointcircle.core.entity.User;
import com.pointcircle.core.repository.UserRepository;
import com.pointcircle.core.web.EntityVo;
import com.pointcircle.core.web.FormVo;
import com.pointcircle.core.web.IAddRest;
import com.pointcircle.core.web.IFindByIdRest;
import com.pointcircle.core.web.RestResponseElement;
import com.pointcircle.core.web.RestResponseList;
import com.pointcircle.estate.server.framework.entity.BatchType;
import com.pointcircle.estate.server.framework.entity.Building;
import com.pointcircle.estate.server.framework.entity.CheckItemGuideline;
import com.pointcircle.estate.server.framework.entity.CheckQualityProblem;
import com.pointcircle.estate.server.framework.entity.Floor;
import com.pointcircle.estate.server.framework.entity.House;
import com.pointcircle.estate.server.framework.entity.ProblemClass;
import com.pointcircle.estate.server.framework.entity.ProblemStatus;
import com.pointcircle.estate.server.framework.entity.Project;
import com.pointcircle.estate.server.framework.entity.QualityMeasureCheckQualityCc;
import com.pointcircle.estate.server.framework.entity.QualityMeasureCheckQualityProblem;
import com.pointcircle.estate.server.framework.entity.QualityMeasureCheckQualityRepair;
import com.pointcircle.estate.server.framework.entity.Unit;
import com.pointcircle.estate.server.framework.entity.UserInfo;
import com.pointcircle.estate.server.framework.repository.BuildingRepository;
import com.pointcircle.estate.server.framework.repository.CheckItemGuidelineRepository;
import com.pointcircle.estate.server.framework.repository.FloorRepository;
import com.pointcircle.estate.server.framework.repository.HouseRepository;
import com.pointcircle.estate.server.framework.repository.ProblemClassRepository;
import com.pointcircle.estate.server.framework.repository.ProjectRepository;
import com.pointcircle.estate.server.framework.repository.QualityMeasureCheckQualityCcRepository;
import com.pointcircle.estate.server.framework.repository.QualityMeasureCheckQualityProblemRepository;
import com.pointcircle.estate.server.framework.repository.QualityMeasureCheckQualityRepairRepository;
import com.pointcircle.estate.server.framework.repository.UnitRepository;
import com.pointcircle.estate.server.framework.repository.UserInfoRepository;
import com.pointcircle.estate.server.framework.web.api.CheckQualityProblemApi.CheckQualityProblemFormVo;
import com.pointcircle.estate.server.framework.web.api.CheckQualityProblemApi.CheckQualityProblemFormVo.Photo;
import com.pointcircle.estate.server.framework.web.api.CheckQualityProblemApi.CheckQualityProblemFormVo.ProblemValue;

import lombok.Getter;
import lombok.Setter;
import net.coobird.thumbnailator.Thumbnails;

@RestController
@RequestMapping("/rest/api/v3/qualityMeasureCheckQualityProblem")
public class QualityMeasureCheckQualityProblemApi implements 
	IFindByIdRest<QualityMeasureCheckQualityProblem, String, QualityMeasureCheckQualityProblemApi.QualityMeasureCheckQualityProblemEntityVo>,
	IAddRest<QualityMeasureCheckQualityProblem, String, QualityMeasureCheckQualityProblemApi.QualityMeasureCheckQualityProblemEntityVo, QualityMeasureCheckQualityProblemApi.QualityMeasureCheckQualityProblemFormVo>{
	
	@Autowired
	private QualityMeasureCheckQualityProblemRepository repository;
	
	@Autowired
	private ProjectRepository projectRepository;
	
	@Autowired
	private BuildingRepository buildingRepository;
	
	@Autowired
	private UnitRepository unitRepository;
	
	@Autowired
	private FloorRepository floorRepository;
	
	@Autowired
	private HouseRepository houseRepository;
	
	@Autowired
	private ProblemClassRepository problemClassRepository;
	
	@Autowired
	private CheckItemGuidelineRepository checkItemGuidelineRepository;
	
	@Autowired
	private UserRepository userRepository;
	
	@Autowired
	private QualityMeasureCheckQualityRepairRepository qualityMeasureCheckQualityRepairRepository;
	
	@Autowired
	private QualityMeasureCheckQualityCcRepository qualityMeasureCheckQualityCcRepository;
	
	@Autowired
	private UserInfoRepository userInfoRepository;
	
	@Value("${web.upload-path.img}")
	private String uploadPathImg;
	
	@Value("${web.img-url}")
	private String webImgUrl;
	
	public class QualityMeasureCheckQualityProblemEntityVo extends EntityVo<QualityMeasureCheckQualityProblem, String> {
		private List<String> ccIds = new LinkedList<String>();
		public QualityMeasureCheckQualityProblemEntityVo(QualityMeasureCheckQualityProblem entity) {
			super(entity);
		}
		@JsonProperty("id")
		public String getId() {
			return entity.getId();
		}
		
		@JsonProperty(value = "updateTimestamp")
		public Long getUpdateTimestamp() {
			if(entity.getUpdateTime() != null) {
				return entity.getUpdateTime().getTime();
			} else {
				Date dateReturn = entity.getRegistDate();
				if(entity.getRepairDate() != null && dateReturn.before(entity.getRepairDate())) {
					dateReturn = entity.getRepairDate();
				}
				if(entity.getSentBackDate() != null &&  dateReturn.before(entity.getSentBackDate())) {
					dateReturn = entity.getSentBackDate();
				}
				return dateReturn.getTime();
			}
		}
		@JsonProperty("itemId")
		public String getItemId() {
			return entity.getItemId();
		}
		@JsonProperty("bidSectionId")
		public String getBidSectionId() {
			return entity.getBuilding().getBidSectionId();
		}
		@JsonProperty("buildingId")
		public String getBuildingId() {
			return entity.getBuildingId();
		}
		@JsonProperty("buildingName")
		public String getBuildingName() {
			if(entity.getBuildingId() != null) {
				return entity.getBuilding().getBuildingName();
			} else {
				return null;
			}
		}
		@JsonProperty("unitId")
		public String getUnitId() {
			return entity.getUnitId();
		}
		@JsonProperty("unitName")
		public String getUnitName() {
			if(entity.getUnitId() != null) {
				return entity.getUnit().getUnitName();
			} else {
				return null;
			}
		}
		@JsonProperty("floorId")
		public String getFloorId() {
			return entity.getFloorId();
		}
		@JsonProperty("floorName")
		public String getFloorName() {
			if(entity.getFloorId() != null) {
				return entity.getFloor().getFloorName();
			} else {
				return null;
			}
		}
		@JsonProperty("roomId")
		public String getRoomId() {
			return entity.getRoomId();
		}
		@JsonProperty("roomName")
		public String getRoomName() {
			if(entity.getRoomId() != null) {
				return entity.getHouse().getHouseName();
			} else {
				return null;
			}
		}
		@JsonProperty("houseTypeId")
		public String getHouseTypeId() {
			if(entity.getRoomId() != null) {
				return entity.getHouse().getHouseTypeId();
			} else {
				return null;
			}
		}
		@JsonProperty("status")
		public ProblemStatus getStatus() {
			return entity.getStatus();
		}
		@JsonProperty("drawingFile")
		public String getDrawdingFile() {
			if(StringUtils.isEmpty(entity.getDrawingFile())) {
				return "[]";
			} else {
				return entity.getDrawingFile();
			}
		}
		@JsonProperty("problemValues")
		public String getProblemValues() {
			if(StringUtils.isEmpty(entity.getProblemValues())) {
				return "[]";
			} else {
				return entity.getProblemValues();
			}
		}
		@JsonProperty("batchType")
		public BatchType getBatchType() {
			return entity.getBatchType();
		}
		@JsonProperty("registBy")
		public String getRegistBy() {
			return entity.getRegistByUserId();
		}
		@JsonProperty("registTimestamp")
		public Long registTimestamp() {
			return entity.getRegistDate() != null ? entity.getRegistDate().getTime() : null;
		}
		@JsonProperty("remark")
		public String getRemark() {
			return entity.getRemark();
		}
		@JsonProperty("imageFile")
		public String getImageFile() {
			if(StringUtils.isEmpty(entity.getImageFile())) {
				return "[]";
			} else {
				return entity.getImageFile();
			}
		}
		@JsonProperty("smallImageFile")
		public String getSmallImageFile() {
			if(StringUtils.isEmpty(entity.getSmallImageFile())) {
				return "[]";
			} else {
				return entity.getSmallImageFile();
			}
		}
		@JsonProperty("repairBy")
		public String getRepairBy() {
			return entity.getRepairByUserId();
		}
		@JsonProperty("registDate")
		public Long getRegistDate() {
			return entity.getRegistDate() != null ? entity.getRegistDate().getTime() : null;
		}
		@JsonProperty("repairTimestamp")
		public Long repairTimestamp() {
			return entity.getRepairDate() != null ? entity.getRepairDate().getTime() : null;
		}
		
		@JsonProperty("repairDate")
		public Long repairDate() {
			return entity.getRepairDate() != null ? entity.getRepairDate().getTime() : null;
		}
		
		@JsonProperty("repairRemark")
		public String getRepairRemark() {
			return entity.getRepairRemark();
		}
		@JsonProperty("repairImageFile")
		public String getRepairImageFile() {
			if(StringUtils.isEmpty(entity.getRepairImageFile())) {
				return "[]";
			} else {
				return entity.getRepairImageFile();
			}
		}
		@JsonProperty("smallRepairImageFile")
		public String getSmallRepairImageFile() {
			if(StringUtils.isEmpty(entity.getSmallRepairImageFile())) {
				return "[]";
			} else {
				return entity.getSmallRepairImageFile();
			}
		}
		@JsonProperty("measurePoints")
		public Integer getMeasurePoints() {
			return entity.getMeasurePoints();
		}
		@JsonProperty("problemPoints")
		public Integer getProblemPoints() {
			return entity.getProblemPoints();
		}
		@JsonProperty("standardMin")
		public Double getStandardMin() {
			return entity.getStandardMin();
		}
		@JsonProperty("standardMax")
		public Double getStarndardMax() {
			return entity.getStarndardMax();
		}
		@JsonProperty("sentBackDate")
		public Long sentBackDate() {
			return entity.getSentBackDate() != null ? entity.getSentBackDate().getTime() : null;
		}
		@JsonProperty("sentBackTimes")
		public Integer getSentBackTimes() {
			return entity.getSentBackTimes();
		}
		@JsonProperty("sentBackRemark")
		public String getSentBackRemark() {
			return entity.getSentBackRemark();
		}
		@JsonProperty("sentBackImageFile")
		public String getSentBackImageFile() {
			if(StringUtils.isEmpty(entity.getSentBackImageFile())) {
				return "[]";
			} else {
				return entity.getSentBackImageFile();
			}
		}
		@JsonProperty("smallSentBackImageFile")
		public String getSmallSentBackImageFile() {
			if(StringUtils.isEmpty(entity.getSmallSentBackImageFile())) {
				return "[]";
			} else {
				return entity.getSmallSentBackImageFile();
			}
		}
		@JsonProperty("appPermission")
		public String getAppPermission() {
			return entity.getAppPermission();
		}
		public void setCcIds(List<String> ccIds) {
			this.ccIds = ccIds;
		}
		@JsonProperty("ccs")
		public String getCcs() {
			JSONArray array = new JSONArray(ccIds);
			return array.toString();
		}
	}
	
	@Getter
	@Setter
	public static class QualityMeasureCheckQualityProblemFormVo extends FormVo<String> {
		@Getter
		@Setter
		public static class ProblemValue {
			private String x;
			private String y;
		}
		@Getter
		@Setter
		public static class Photo {
			private String url;
		}
		@NotBlank(message = "楼栋不能为空")
		private String buildingId;
		private String unitId;
		@NotBlank(message = "楼层不能为空")
		private String floorId;
		private String houseId;
		@NotBlank(message = "检查项不能为空")
		private String itemId;
		private Integer measurePoints;
		@NotBlank(message = "登记人不能为空")
		private String regist;
		private String remark;
		private String repair;
		private List<String> pointsX = new LinkedList<String>();
		private List<String> pointsY = new LinkedList<String>();
		private List<String> ccs = new LinkedList<String>();
		private List<Photo> photos = new LinkedList<Photo>();
		private List<String> values = new LinkedList<String>();
	}
	
	@Setter
	@Getter
	public static class ProblemRepair {
		@Getter
		@Setter
		public static class Photo {
			private String url;
		}
		@NotBlank(message = "检查项不能为空")
		private String qualityMeasureCheckqualityProblemId;
		@NotBlank(message = "整改人不能为空")
		private String repairUserId;
		private String repairRemark;
		private List<Photo> photos = new LinkedList<Photo>();
	}

	@Override
	public IRepository<QualityMeasureCheckQualityProblem, String> getRepository() {
		return repository;
	}
	
	@GetMapping("findByProjectIdAndItemId")
	public RestResponseList findByProjectId(@RequestParam("projectId") String projectId,
			@RequestParam("itemId") String itemId) {
		Project project = projectRepository.findOne(projectId);
		ProblemClass problemClass = problemClassRepository.findOne(itemId);
		List<Building> buildings = buildingRepository.findByProject(project);
		List<QualityMeasureCheckQualityProblem> problems = new LinkedList<QualityMeasureCheckQualityProblem>();
		buildings.forEach((building) -> {
			problems.addAll(repository.findByBuildingAndProblemClass(building, problemClass));
		});
		if(problems.size() == 0) {
			RestResponseList response = new RestResponseList();
			response.setSuccess(true);
			return response;
		}
		Map<String, List<String>> ccMap = 
			new HashMap<String, List<String>>();
		qualityMeasureCheckQualityCcRepository.findByQualityMeasureCheckQualityProblemIn(problems)
			.forEach((cc) -> {
				List<String> ccIds = ccMap.get(cc.getQualityMeasureCheckqualityProblemId());
				if(ccIds == null) {
					ccIds = new LinkedList<String>();
					ccMap.put(cc.getQualityMeasureCheckqualityProblemId(), ccIds);
				}
				ccIds.add(cc.getCcId());
			});
		List<QualityMeasureCheckQualityProblemEntityVo> vos = 
			problems.stream().map((problem) -> {
				QualityMeasureCheckQualityProblemEntityVo vo = 
					new QualityMeasureCheckQualityProblemEntityVo(problem);
				vo.setCcIds(ccMap.get(problem.getId()));
				return vo;
			}).collect(Collectors.toList());
		RestResponseList response = new RestResponseList();
		response.setSuccess(true);
		response.setList(vos);
		return response;
	}
	
	@GetMapping("findByFloorIdAndItemId")
	public RestResponseList findByFloorIdAndItemId(@RequestParam("floorId") String floorId,
			@RequestParam("itemId") String itemId) {
		
		List<QualityMeasureCheckQualityProblem> problems = repository.findProblemsByFloorIdAndItemId(floorId, itemId);
		List<QualityMeasureCheckQualityProblemEntityVo> vos = new ArrayList<QualityMeasureCheckQualityProblemApi.QualityMeasureCheckQualityProblemEntityVo>();
		Map<String, List<String>> ccMap = 
				new HashMap<String, List<String>>();
			qualityMeasureCheckQualityCcRepository.findByQualityMeasureCheckQualityProblemIn(problems)
				.forEach((cc) -> {
					List<String> ccIds = ccMap.get(cc.getQualityMeasureCheckqualityProblemId());
					if(ccIds == null) {
						ccIds = new LinkedList<String>();
						ccMap.put(cc.getQualityMeasureCheckqualityProblemId(), ccIds);
					}
					ccIds.add(cc.getCcId());
				});
		for(QualityMeasureCheckQualityProblem problem : problems) {
			QualityMeasureCheckQualityProblemEntityVo vo = new QualityMeasureCheckQualityProblemEntityVo(problem);
			vo.setCcIds(ccMap.get(problem.getId()));
			vos.add(vo);
		}
		RestResponseList response = new RestResponseList();
		response.setSuccess(true);
		response.setList(vos);
		return response;
	}
	
	@PostMapping("regist")
	@Transactional
	public RestResponseElement regist(
			@RequestParam(value = "buildingId") String buildingId,
			@RequestParam(value = "unitId", required = false) String unitId,
			@RequestParam(value = "floorId") String floorId,
			@RequestParam(value = "houseId", required = false) String houseId,
			@RequestParam(value = "itemId") String itemId,
			@RequestParam(value = "measurePoints") Integer measurePoints,
			@RequestParam(value = "values", required = false) List<String> values,
			@RequestParam(value = "pointsX", required = false) List<String> pointsX,
			@RequestParam(value = "pointsY", required = false) List<String> pointsY,
			@RequestParam(value = "photos", required = false) List<MultipartFile> multipartFiles,
			@RequestParam(value = "remark", required = false) String remark,
			@RequestParam(value = "regist") String regist,
			@RequestParam(value = "repair", required = false) String repair,
			@RequestParam(value = "ccs", required = false) List<String> ccs) throws IOException {
		Building building = buildingRepository.findOne(buildingId);
		Floor floor = floorRepository.findOne(floorId);
		Unit unit = unitId == null ? null : unitRepository.findOne(unitId);
		House house = houseId == null ? null : houseRepository.findOne(houseId);
		ProblemClass problemClass = problemClassRepository.findOne(itemId);
		CheckItemGuideline checkItemGuideline = checkItemGuidelineRepository.findByItem(problemClass);
		User registUser = userRepository.findOne(regist);
		UserInfo registUserInfo = userInfoRepository.findByUser(registUser);
		User repairUser = repair == null ? null : userRepository.findOne(repair);
		List<User> ccUsers = ccs == null ? new LinkedList<User>() : userRepository.findAllById(ccs);
		QualityMeasureCheckQualityProblem checkQualityProblem =
			new QualityMeasureCheckQualityProblem();
		checkQualityProblem.setBatchType(BatchType.实测实量);
		checkQualityProblem.setHouse(house);
		checkQualityProblem.setUnit(unit);
		checkQualityProblem.setFloor(floor);
		checkQualityProblem.setBuilding(building);
		checkQualityProblem.setProblemClass(problemClass);
		checkQualityProblem.setRegistBy(registUser);
		checkQualityProblem.setRegistDate(new Date());
		checkQualityProblem.setImageFile("[]");
		checkQualityProblem.setRepairImageFile("[]");
		checkQualityProblem.setRemark(remark);
		checkQualityProblem.setRepairRemark("");
		checkQualityProblem.setStandardMin(checkItemGuideline.getStandardMin());
		checkQualityProblem.setStarndardMax(checkItemGuideline.getStandardMax());
		checkQualityProblem.setMeasurePoints(measurePoints);
		checkQualityProblem.setProblemPoints(0);
		checkQualityProblem.setProblemValues("[]");
		checkQualityProblem.setDrawingFile("[]");
		checkQualityProblem.setAppPermission(registUserInfo == null ? null : registUserInfo.getAppPermission());
		if(values != null) {
			checkQualityProblem.setProblemPoints(values.size());
			JSONArray array = new JSONArray();
			for(int i = 0; i < values.size(); i++) {
				JSONObject object = new JSONObject();
				object.put("val", values.get(i));
				if(pointsX != null && pointsX.size() > i) {
					String x = pointsX.get(i);
					String y = pointsY.get(i);
					object.put("x", x);
					object.put("y", y);
					object.put("found", true);
					object.put("color", "#14ff56");
				}
				array.put(object);
			}
			checkQualityProblem.setProblemValues(array.toString());
		}
		if(house != null && house.getHouseType() != null) {
			String houseTypeImageUrl = house.getHouseType().getUrl();
			JSONArray array = new JSONArray();
			JSONObject object = new JSONObject();
			object.put("url", houseTypeImageUrl);  
			object.put("type", "户型图");
			array.put(object);
			checkQualityProblem.setDrawingFile(array.toString());
		}
		JSONArray imageFileJson = new JSONArray();
		JSONArray smallImageFileJson = new JSONArray();
		if(multipartFiles != null) {
			for(MultipartFile multipartFile : multipartFiles) {
				String fileName = UUID.randomUUID().toString() + ".jpg";
				String filePath = uploadPathImg + "/" + fileName;
				File f = new File(filePath);
				FileOutputStream fos = new FileOutputStream(f);
				InputStream is = multipartFile.getInputStream();
				byte[] bytes = new byte[1024];
				do {
					int len = is.read(bytes);
					if(len == -1) {
						break;
					}
					fos.write(bytes, 0, len);
				} while(true);
				fos.close();
				JSONObject json = new JSONObject();
				String url = webImgUrl + fileName;
				json.put("url", url);
				imageFileJson.put(json);
				
				String smallFileName = "small_" + fileName;
				String smallFilePath = uploadPathImg + "/" + smallFileName;
				Thumbnails.of(filePath) 
		        	.scale(0.2f) 
		        	.outputQuality(0.5f) 
		        	.toFile(smallFilePath);
				json = new JSONObject();
				url = webImgUrl + smallFileName;
				json.put("url", url);
				smallImageFileJson.put(json);
			}
		} 
		checkQualityProblem.setImageFile(imageFileJson.toString());
		checkQualityProblem.setSmallImageFile(smallImageFileJson.toString());
		if(repairUser != null) {
			checkQualityProblem.setStatus(ProblemStatus.待整改);
			this.getRepository().saveAndFlush(checkQualityProblem);
			Boolean hasRead = false;
			QualityMeasureCheckQualityRepair qualityMeasureRepair = new QualityMeasureCheckQualityRepair();
			qualityMeasureRepair.setRepair(repairUser);
			qualityMeasureRepair.setQualityMeasureCheckQualityProblem(checkQualityProblem);
			qualityMeasureRepair.setHasRead(hasRead);
			qualityMeasureCheckQualityRepairRepository.saveAndFlush(qualityMeasureRepair);
		} else {
			checkQualityProblem.setStatus(ProblemStatus.检查完毕);
			this.getRepository().saveAndFlush(checkQualityProblem);
		}
		for(User ccUser : ccUsers) {
			QualityMeasureCheckQualityCc qualityMeasureCc = new QualityMeasureCheckQualityCc();
			qualityMeasureCc.setCc(ccUser);
			qualityMeasureCc.setQualityMeasureCheckQualityProblem(checkQualityProblem);
			qualityMeasureCheckQualityCcRepository.saveAndFlush(qualityMeasureCc);
		}
		QualityMeasureCheckQualityProblemEntityVo vo = new QualityMeasureCheckQualityProblemEntityVo(checkQualityProblem);
		vo.setCcIds(ccUsers.stream().map((ccUser) -> {
			return ccUser.getId();
		}).collect(Collectors.toList()));
		RestResponseElement response = new RestResponseElement();
		response.setElement(vo);
		return response;
	}
	
	@PostMapping("modify")
	@Transactional
	public RestResponseElement modify(
			@RequestParam(value = "qualityMeasureProblemId") String qualityMeasureProblemId,
			@RequestParam(value = "measurePoints") Integer measurePoints,
			@RequestParam(value = "values", required = false) List<String> values,
			@RequestParam(value = "pointsX", required = false) List<String> pointsX,
			@RequestParam(value = "pointsY", required = false) List<String> pointsY,
			@RequestParam(value = "photos", required = false) List<MultipartFile> multipartFiles,
			@RequestParam(value = "remark", required = false) String remark,
			@RequestParam(value = "regist") String regist,
			@RequestParam(value = "repair", required = false) String repair,
			@RequestParam(value = "ccs", required = false) List<String> ccs) throws IOException {
		User registUser = userRepository.findOne(regist);
		User repairUser = repair == null ? null : userRepository.findOne(repair);
		List<User> ccUsers = ccs == null ? new LinkedList<User>() : userRepository.findAllById(ccs);
		QualityMeasureCheckQualityProblem qualityMeasureProblem = 
			repository.findOne(qualityMeasureProblemId);
		qualityMeasureProblem.setRegistBy(registUser);
		qualityMeasureProblem.setRegistDate(new Date());
		qualityMeasureProblem.setMeasurePoints(measurePoints);
		qualityMeasureProblem.setRemark(remark);
		qualityMeasureProblem.setProblemValues("[]");
		if(values != null) {
			qualityMeasureProblem.setProblemPoints(values.size());
			JSONArray array = new JSONArray();
			for(int i = 0; i < values.size(); i++) {
				JSONObject object = new JSONObject();
				object.put("val", values.get(i));
				if(pointsX != null && pointsX.size() > i) {
					String x = pointsX.get(i);
					String y = pointsY.get(i);
					object.put("x", x);
					object.put("y", y);
					object.put("found", true);
					object.put("color", "#14ff56");
				}
				array.put(object);
			}
			qualityMeasureProblem.setProblemValues(array.toString());
		}

		JSONArray imageFileJson = new JSONArray();
		JSONArray smallImageFileJson = new JSONArray();
		if(multipartFiles != null) {
			for(MultipartFile multipartFile : multipartFiles) {
				String fileName = UUID.randomUUID().toString() + ".jpg";
				String filePath = uploadPathImg + "/" + fileName;
				File f = new File(filePath);
				FileOutputStream fos = new FileOutputStream(f);
				InputStream is = multipartFile.getInputStream();
				byte[] bytes = new byte[1024];
				do {
					int len = is.read(bytes);
					if(len == -1) {
						break;
					}
					fos.write(bytes, 0, len);
				} while(true);
				fos.close();
				JSONObject json = new JSONObject();
				String url = webImgUrl + fileName;
				json.put("url", url);
				imageFileJson.put(json);
				
				String smallFileName = "small_" + fileName;
				String smallFilePath = uploadPathImg + "/" + smallFileName;
				Thumbnails.of(filePath) 
		        	.scale(0.2f) 
		        	.outputQuality(0.5f) 
		        	.toFile(smallFilePath);
				json = new JSONObject();
				url = webImgUrl + smallFileName;
				json.put("url", url);
				smallImageFileJson.put(json);
			}
		} 
		qualityMeasureProblem.setImageFile(imageFileJson.toString());
		qualityMeasureProblem.setSmallImageFile(smallImageFileJson.toString());
		
		List<QualityMeasureCheckQualityRepair> qualityMeasureRepairs =
			qualityMeasureCheckQualityRepairRepository.findByQualityMeasureCheckQualityProblem(qualityMeasureProblem);
		qualityMeasureCheckQualityRepairRepository.deleteAll(qualityMeasureRepairs);
		if(repairUser != null && qualityMeasureProblem.getRepairBy() == null) {
			qualityMeasureProblem.setStatus(ProblemStatus.待整改);
			this.getRepository().saveAndFlush(qualityMeasureProblem);
			Boolean hasRead = false;
			QualityMeasureCheckQualityRepair qualityMeasureRepair = new QualityMeasureCheckQualityRepair();
			qualityMeasureRepair.setRepair(repairUser);
			qualityMeasureRepair.setQualityMeasureCheckQualityProblem(qualityMeasureProblem);
			qualityMeasureRepair.setHasRead(hasRead);
			qualityMeasureCheckQualityRepairRepository.saveAndFlush(qualityMeasureRepair);
		} else {
			qualityMeasureProblem.setStatus(ProblemStatus.检查完毕);
			this.getRepository().saveAndFlush(qualityMeasureProblem);
		}
		if(qualityMeasureProblem.getRepairBy() == null) {
			List<QualityMeasureCheckQualityCc> qualityMeasureCcs =
				qualityMeasureCheckQualityCcRepository.findByQualityMeasureCheckQualityProblem(qualityMeasureProblem);
			qualityMeasureCheckQualityCcRepository.deleteAll(qualityMeasureCcs);
			for(User ccUser : ccUsers) {
				QualityMeasureCheckQualityCc qualityMeasureCc = new QualityMeasureCheckQualityCc();
				qualityMeasureCc.setCc(ccUser);
				qualityMeasureCc.setQualityMeasureCheckQualityProblem(qualityMeasureProblem);
				qualityMeasureCheckQualityCcRepository.saveAndFlush(qualityMeasureCc);
			}
		}
		QualityMeasureCheckQualityProblemEntityVo vo = 
			new QualityMeasureCheckQualityProblemEntityVo(qualityMeasureProblem);
		vo.setCcIds(ccUsers.stream().map((ccUser) -> {
			return ccUser.getId();
		}).collect(Collectors.toList()));
		RestResponseElement response =new RestResponseElement();
		response.setElement(vo);
		return response;
	}
	
	@PostMapping("problemRepair")
	public RestResponseElement problemRepair (
			/*@RequestParam(value = "qualityMeasureCheckqualityProblemId") String qualityMeasureCheckqualityProblemId,
			@RequestParam(value = "repairUserId") String repairUserId,
			@RequestParam(value = "repairRemark", required = false) String repairRemark,
			@RequestParam(value = "photos", required = false) List<> photos*/
			@Valid @RequestBody ProblemRepair problemRepair) 
				throws IOException, JSONException {
		ObjectMapper mapper = new ObjectMapper();
		QualityMeasureCheckQualityProblem problem = repository.findOne(problemRepair.qualityMeasureCheckqualityProblemId);
		problem.setStatus(ProblemStatus.已整改);
		problem.setRepairBy(userRepository.findOne(problemRepair.repairUserId));
		problem.setRepairRemark(problemRepair.repairRemark);
		problem.setRepairDate(new Date());
		
		problem.setRepairImageFile(mapper.writeValueAsString(problemRepair.photos));
		for(com.pointcircle.estate.server.framework.web.api.QualityMeasureCheckQualityProblemApi.ProblemRepair.Photo photo : problemRepair.photos) {
			photo.setUrl(photo.url + "?x-oss-process=image/resize,m_fixed,h_80,w_80");
		}
		problem.setSmallRepairImageFile(mapper.writeValueAsString(problemRepair.photos));
		this.getRepository().saveAndFlush(problem);
		QualityMeasureCheckQualityProblemEntityVo entityVo = new QualityMeasureCheckQualityProblemEntityVo(problem);
		entityVo.setCcIds(qualityMeasureCheckQualityCcRepository.findCcIdsByQualityMeasureCheckQualityProblemId(problem.getId()));
		RestResponseElement response = new RestResponseElement();
		response.setElement(entityVo);
		return response;
	}
	
	@PostMapping("problemRepairCompleted")
	public RestResponseElement problemRepairCompleted (/*
			@RequestParam(value = "qualityMeasureCheckQualityProblemId") String qualityMeasureCheckQualityProblemId,
			@RequestParam(value = "registUserId") String registUserId,
			@RequestParam(value = "values", required = false) List<String> values,
			@RequestParam(value = "pointsX", required = false) List<String> pointsX,
			@RequestParam(value = "pointsY", required = false) List<String> pointsY,
			@RequestParam(value = "measurePoints", required = false) Integer measurePoints*/
			@Valid @RequestBody ProblemRepairCompleted problemRepairCompleted) 
				throws IOException, JSONException {
		QualityMeasureCheckQualityProblem qualityMeasureCheckQualityProblem = repository.findOne(problemRepairCompleted.getQualityMeasureCheckQualityProblemId());
		qualityMeasureCheckQualityProblem.setStatus(ProblemStatus.检查完毕);
		if(problemRepairCompleted.getMeasurePoints() != null) {
			qualityMeasureCheckQualityProblem.setMeasurePoints(problemRepairCompleted.getMeasurePoints());
		}
		if(problemRepairCompleted.getPoints() != null) {
			qualityMeasureCheckQualityProblem.setProblemPoints(problemRepairCompleted.getPoints().size());
			JSONArray array = new JSONArray();
			for(int i = 0; i < problemRepairCompleted.getPoints().size(); i++) {
				JSONObject object = new JSONObject();
				object.put("val", problemRepairCompleted.getPoints().get(i).getValue());
				String x = problemRepairCompleted.getPoints().get(i).getX();
				String y = problemRepairCompleted.getPoints().get(i).getY();
				if(x != null) {
					object.put("x", x);
				}
				if(y != null) {
					object.put("y", y);
				}
				object.put("found", true);
				object.put("color", "#14ff56");
				array.put(object);
			}
			qualityMeasureCheckQualityProblem.setProblemValues(array.toString());
		}
		qualityMeasureCheckQualityProblem.setRegistDate(new Date());
		repository.saveAndFlush(qualityMeasureCheckQualityProblem);
		QualityMeasureCheckQualityProblemEntityVo entityVo = new QualityMeasureCheckQualityProblemEntityVo(qualityMeasureCheckQualityProblem);
		entityVo.setCcIds(qualityMeasureCheckQualityCcRepository.findCcIdsByQualityMeasureCheckQualityProblemId(qualityMeasureCheckQualityProblem.getId()));
		RestResponseElement response = new RestResponseElement();
		response.setElement(entityVo);
		return response;
	}
	
	@PostMapping("problemSendBack")
	public RestResponseElement problemSendBack (
			/*@RequestParam(value = "qualityMeasureCheckQualityProblemId") String qualityMeasureCheckQualityProblemId,
			@RequestParam(value = "sendBackRemark", required = false) String sendBackRemark,
			@RequestParam(value = "photos", required = false) List<MultipartFile> multipartFiles*/
			@Valid @RequestBody ProblemSendBack problemSendBack) 
				throws IOException, JSONException {
		ObjectMapper mapper = new ObjectMapper();
		QualityMeasureCheckQualityProblem qualityMeasureCheckQualityProblem = repository.findOne(problemSendBack.getQualityMeasureCheckQualityProblemId());
		qualityMeasureCheckQualityProblem.setStatus(ProblemStatus.待整改);
		if(qualityMeasureCheckQualityProblem.getSentBackTimes() == null) {
			qualityMeasureCheckQualityProblem.setSentBackTimes(1);
		}else {
			qualityMeasureCheckQualityProblem.setSentBackTimes(qualityMeasureCheckQualityProblem.getSentBackTimes() + 1);
		}
		qualityMeasureCheckQualityProblem.setSentBackDate(new Date());
		qualityMeasureCheckQualityProblem.setSentBackRemark(problemSendBack.getSendBackRemark());
		
		qualityMeasureCheckQualityProblem.setSentBackImageFile(mapper.writeValueAsString(problemSendBack.photos));
		for(com.pointcircle.estate.server.framework.web.api.QualityMeasureCheckQualityProblemApi.ProblemSendBack.Photo photo : problemSendBack.photos) {
			photo.setUrl(photo.url + "?x-oss-process=image/resize,m_fixed,h_80,w_80");
		}
		qualityMeasureCheckQualityProblem.setSmallSentBackImageFile(mapper.writeValueAsString(problemSendBack.photos));
		repository.saveAndFlush(qualityMeasureCheckQualityProblem);

		QualityMeasureCheckQualityProblemEntityVo entityVo = new QualityMeasureCheckQualityProblemEntityVo(qualityMeasureCheckQualityProblem);
		entityVo.setCcIds(qualityMeasureCheckQualityCcRepository.findCcIdsByQualityMeasureCheckQualityProblemId(qualityMeasureCheckQualityProblem.getId()));
		RestResponseElement response = new RestResponseElement();
		response.setElement(entityVo);
		return response;
	}
	@Getter
	@Setter
	public static class ProblemRepairCompleted {
		@Getter
		@Setter
		private static class Point {
			private String value;
			private String x;
			private String y;
		}
		@NotBlank(message = "问题项不能为空")
		private String qualityMeasureCheckQualityProblemId;
		@NotBlank(message = "登记人不能为空")
		private String registUserId;
		private List<Point> points = new LinkedList<QualityMeasureCheckQualityProblemApi.ProblemRepairCompleted.Point>();
		private Integer measurePoints;
		
	}
	
	@Getter
	@Setter
	public static class ProblemSendBack {
		@Getter
		@Setter
		public static class Photo {
			private String url;
		}
		@NotBlank(message = "检查项不能为空")
		private String qualityMeasureCheckQualityProblemId;
		private String sendBackRemark;
		private List<Photo> photos = new LinkedList<Photo>();
	}
	
	@Override
	public void processAddEntity(QualityMeasureCheckQualityProblemFormVo form, QualityMeasureCheckQualityProblem entity) throws JsonProcessingException {
		ObjectMapper mapper = new ObjectMapper();
		Building building = buildingRepository.findOne(form.buildingId);
		Floor floor = floorRepository.findOne(form.floorId);
		Unit unit = form.unitId == null ? null : unitRepository.findOne(form.unitId);
		House house = form.houseId == null ? null : houseRepository.findOne(form.houseId);
		ProblemClass problemClass = problemClassRepository.findOne(form.itemId);
		CheckItemGuideline checkItemGuideline = checkItemGuidelineRepository.findByItem(problemClass);
		User registUser = userRepository.findOne(form.regist);
		UserInfo registUserInfo = userInfoRepository.findByUser(registUser);
		User repairUser = form.repair == null ? null : userRepository.findOne(form.repair);
		List<User> ccUsers = form.ccs == null ? new LinkedList<User>() : userRepository.findAllById(form.ccs);
		entity.setBatchType(BatchType.实测实量);
		entity.setHouse(house);
		entity.setUnit(unit);
		entity.setFloor(floor);
		entity.setBuilding(building);
		entity.setProblemClass(problemClass);
		entity.setRegistBy(registUser);
		entity.setRegistDate(new Date());
		entity.setImageFile("[]");
		entity.setRepairImageFile("[]");
		entity.setRemark(form.remark);
		entity.setRepairRemark("");
		entity.setStandardMin(checkItemGuideline.getStandardMin());
		entity.setStarndardMax(checkItemGuideline.getStandardMax());
		entity.setMeasurePoints(form.measurePoints);
		entity.setProblemPoints(0);
		entity.setProblemValues("[]");
		entity.setDrawingFile("[]");
		entity.setAppPermission(registUserInfo == null ? null : registUserInfo.getAppPermission());
		if(form.values != null) {
			entity.setProblemPoints(form.values.size());
			JSONArray array = new JSONArray();
			for(int i = 0; i < form.values.size(); i++) {
				JSONObject object = new JSONObject();
				object.put("val", form.values.get(i));
				if(form.pointsX != null && form.pointsX.size() > i) {
					String x = form.pointsX.get(i);
					String y = form.pointsY.get(i);
					object.put("x", x);
					object.put("y", y);
					object.put("found", true);
					object.put("color", "#14ff56");
				}
				array.put(object);
			}
			entity.setProblemValues(array.toString());
		}
		if(house != null && house.getHouseType() != null) {
			String houseTypeImageUrl = house.getHouseType().getUrl();
			JSONArray array = new JSONArray();
			JSONObject object = new JSONObject();
			object.put("url", houseTypeImageUrl);  
			object.put("type", "户型图");
			array.put(object);
			entity.setDrawingFile(array.toString());
		}
		entity.setImageFile(mapper.writeValueAsString(form.photos));
		for(com.pointcircle.estate.server.framework.web.api.QualityMeasureCheckQualityProblemApi.QualityMeasureCheckQualityProblemFormVo.Photo photo : form.photos) {
			photo.setUrl(photo.url + "?x-oss-process=image/resize,m_fixed,h_80,w_80");
		}
		entity.setSmallImageFile(mapper.writeValueAsString(form.photos));
		if(repairUser != null) {
			entity.setStatus(ProblemStatus.待整改);
			this.getRepository().saveAndFlush(entity);
			Boolean hasRead = false;
			QualityMeasureCheckQualityRepair qualityMeasureRepair = new QualityMeasureCheckQualityRepair();
			qualityMeasureRepair.setRepair(repairUser);
			qualityMeasureRepair.setQualityMeasureCheckQualityProblem(entity);
			qualityMeasureRepair.setHasRead(hasRead);
			qualityMeasureCheckQualityRepairRepository.saveAndFlush(qualityMeasureRepair);
		} else {
			entity.setStatus(ProblemStatus.检查完毕);
			this.getRepository().saveAndFlush(entity);
		}
		for(User ccUser : ccUsers) {
			QualityMeasureCheckQualityCc qualityMeasureCc = new QualityMeasureCheckQualityCc();
			qualityMeasureCc.setCc(ccUser);
			qualityMeasureCc.setQualityMeasureCheckQualityProblem(entity);
			qualityMeasureCheckQualityCcRepository.saveAndFlush(qualityMeasureCc);
		}
		QualityMeasureCheckQualityProblemEntityVo vo = new QualityMeasureCheckQualityProblemEntityVo(entity);
		vo.setCcIds(ccUsers.stream().map((ccUser) -> {
			return ccUser.getId();
		}).collect(Collectors.toList()));
	}
}
